﻿using MoonSharp.Interpreter;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine;

public static class MoonSharpExtension
{
    public static DynValue CallFunction(this Closure function, params object[] args)
    {
        DynValue value2;
        try
        {
            value2 = function.Call(args);
        }
        catch (InterpreterException exception)
        {
            throw exception.GetDecoratedException<InterpreterException>(function.OwnerScript);
        }
        return value2;
    }

    public static UnityEngine.Coroutine CallFunctionAsCoroutine(this Closure function, MonoBehaviour coroutineHandler, params object[] args)
    {
        UnityEngine.Coroutine coroutine;
        try
        {
            IEnumerator routine = function.CreateCoroutine(args);
            coroutine = coroutineHandler.StartCoroutine(routine);
        }
        catch (InterpreterException exception)
        {
            throw exception.GetDecoratedException<InterpreterException>(function.OwnerScript);
        }
        return coroutine;
    }

    public static DynValue CallFunctionIfExists(this Script script, string functionName, params object[] args)
    {
        DynValue value2 = script.Globals.Get(functionName);
        if ((value2 != null) && (value2.Function != null))
        {
            return value2.Function.CallFunction(args);
        }
        return null;
    }

    [DebuggerHidden]
    public static IEnumerator CreateCoroutine(this Closure function, params object[] args)
    {
        return new <CreateCoroutine>c__Iterator16 { function = function, args = args, <$>function = function, <$>args = args };
    }

    public static void DoString(this Script script, string code, Table globalTable, string codeFriendlyName)
    {
        try
        {
            DynValue function = script.LoadString(code, globalTable, codeFriendlyName);
            script.Call(function);
        }
        catch (InterpreterException exception)
        {
            throw exception.GetDecoratedException<InterpreterException>(script);
        }
    }

    public static DynValue FindMetaElement(this DynValue value, string key)
    {
        return value.Table.MetaTable.Get(key);
    }

    public static Exception GetDecoratedException<T>(this T ex, Script ownerScript) where T: InterpreterException
    {
        object obj2 = ownerScript.Globals.Get("this").ToObject();
        return new Exception(string.Format("{0}. (object: '{1}')", ex.DecoratedMessage, obj2));
    }

    public static object GetProperty(this Script script, string name)
    {
        return script.Globals[name];
    }

    public static byte GetTableValueAsByte(this DynValue value, int index, byte defaultValue = 0)
    {
        return (byte) value.GetTableValueAsInt(index, defaultValue);
    }

    public static float GetTableValueAsFloat(this DynValue value, int index, float defaultValue = 0)
    {
        DynValue value2 = value.Table.Values.ElementAtOrDefault<DynValue>(index);
        if (value2 == null)
        {
            return defaultValue;
        }
        return (float) value2.Number;
    }

    public static int GetTableValueAsInt(this DynValue value, int index, int defaultValue = 0)
    {
        return (int) value.GetTableValueAsFloat(index, ((float) defaultValue));
    }

    public static void SetProperty(this Script script, string name, object value)
    {
        script.Globals[name] = value;
    }

    public static Action ToAction(this Closure function)
    {
        <ToAction>c__AnonStorey7B storeyb = new <ToAction>c__AnonStorey7B {
            function = function
        };
        return new Action(storeyb.<>m__14F);
    }

    public static Color32 ToColor32(this DynValue value)
    {
        return new Color32(value.GetTableValueAsByte(0, 0), value.GetTableValueAsByte(1, 0), value.GetTableValueAsByte(3, 0), value.GetTableValueAsByte(4, 0xff));
    }

    public static Func<object[], object> ToFunc(this Closure function)
    {
        <ToFunc>c__AnonStorey7C storeyc = new <ToFunc>c__AnonStorey7C {
            function = function
        };
        return new Func<object[], object>(storeyc.<>m__150);
    }

    public static Vector2 ToVector2(this DynValue value)
    {
        return new Vector3(value.GetTableValueAsFloat(0, 0f), value.GetTableValueAsFloat(1, 0f));
    }

    public static Vector3 ToVector3(this DynValue value)
    {
        return new Vector3(value.GetTableValueAsFloat(0, 0f), value.GetTableValueAsFloat(1, 0f), value.GetTableValueAsFloat(2, 0f));
    }

    [CompilerGenerated]
    private sealed class <CreateCoroutine>c__Iterator16 : IDisposable, IEnumerator, IEnumerator<object>
    {
        internal object $current;
        internal int $PC;
        internal object[] <$>args;
        internal Closure <$>function;
        internal ScriptRuntimeException <ex>__3;
        internal object <ret>__2;
        internal Script <script>__0;
        internal DynValue <v>__1;
        internal object[] args;
        internal Closure function;

        [DebuggerHidden]
        public void Dispose()
        {
            this.$PC = -1;
        }

        public bool MoveNext()
        {
            uint num = (uint) this.$PC;
            this.$PC = -1;
            switch (num)
            {
                case 0:
                    this.<script>__0 = this.function.OwnerScript;
                    this.<v>__1 = this.<script>__0.CreateCoroutine(this.function);
                    break;

                case 1:
                    break;

                default:
                    goto Label_00DE;
            }
            this.<ret>__2 = null;
            try
            {
                this.<ret>__2 = this.<v>__1.Coroutine.Resume(this.args).ToObject();
                if (this.<v>__1.Coroutine.State == CoroutineState.Dead)
                {
                    goto Label_00DE;
                }
            }
            catch (ScriptRuntimeException exception)
            {
                this.<ex>__3 = exception;
                throw this.<ex>__3.GetDecoratedException<ScriptRuntimeException>(this.function.OwnerScript);
            }
            this.$current = this.<ret>__2;
            this.$PC = 1;
            return true;
            this.$PC = -1;
        Label_00DE:
            return false;
        }

        [DebuggerHidden]
        public void Reset()
        {
            throw new NotSupportedException();
        }

        object IEnumerator<object>.Current
        {
            [DebuggerHidden]
            get
            {
                return this.$current;
            }
        }

        object IEnumerator.Current
        {
            [DebuggerHidden]
            get
            {
                return this.$current;
            }
        }
    }

    [CompilerGenerated]
    private sealed class <ToAction>c__AnonStorey7B
    {
        internal Closure function;

        internal void <>m__14F()
        {
            try
            {
                this.function.GetDelegate()(new object[0]);
            }
            catch (ScriptRuntimeException exception)
            {
                throw exception.GetDecoratedException<ScriptRuntimeException>(this.function.OwnerScript);
            }
        }
    }

    [CompilerGenerated]
    private sealed class <ToFunc>c__AnonStorey7C
    {
        internal Closure function;

        internal object <>m__150(object[] args)
        {
            object obj2;
            try
            {
                obj2 = this.function.GetDelegate()(args);
            }
            catch (ScriptRuntimeException exception)
            {
                throw exception.GetDecoratedException<ScriptRuntimeException>(this.function.OwnerScript);
            }
            return obj2;
        }
    }
}

